#!/usr/bin/python3
# -*- coding:utf-8 -*-
""""
@Author: 李吉凯
@Email: lijk34925@hundsun.com
@Time: 2021/4/22 15:43
"""
import re
import time
import json
from selenium.webdriver.common.action_chains import ActionChains
# from selenium.webdriver.CommonScripts.touch_actions import TouchActions
from selenium.webdriver.remote.webelement import WebElement
from selenium.common import exceptions as SeleniumExceptions
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.common.keys import Keys

from BladeFerm.Lib.Common import *



class ClassSelenium():
    global driver
    def __init__(self, browserType='chrome', saveAsFlag=0, download=None, isCloseBrowser=True):
        '''
        :param browserType:浏览器类型，firefox,chrome,ie
        :param download:
        '''
        self.MyThread = None
        self.MyThreadName = None
        try:
            # webURL = URL
            browserType = browserType.lower()
            # 获取当前系统是32位还是64位
            import platform
            osBit = platform.architecture()[0]
            if browserType == r'firefox':
                self.MyThreadName = r'geckodriver.exe'
                if osBit == '64bit':
                    exePath = toolFolderPath + r'firefox_x64' + pathFlag + r'geckodriver.exe'
                else:
                    exePath = toolFolderPath + r'firefox_win32' + pathFlag + r'geckodriver.exe'
            elif browserType == r'ie':
                self.MyThreadName = r'IEDriverServer.exe'
                if osBit == '64bit':
                    exePath = toolFolderPath + r'IEDriverServer_x64' + pathFlag + r'IEDriverServer.exe'
                else:
                    exePath = toolFolderPath + r'IEDriverServer_win32' + pathFlag + r'IEDriverServer.exe'
            elif browserType == r'chrome':
                self.MyThreadName = r'chromedriver.exe'
                exePath = toolFolderPath + r'chromedriver' + pathFlag + r'chromedriver.exe'
            else:
                logger.warning('请确认浏览器类型是否书写正确，目前只支持：ie、firefox和chrome')
                raise Exception

            # 设置并启动浏览器
            webDriverPath = os.path.abspath(exePath)
            os.environ["webdriver.driver"] = webDriverPath
            # 设置并启动浏览器
            if browserType == r'firefox':
                # 设置firefox下载路径
                profile = webdriver.FirefoxProfile()
                if download:
                    profile.set_preference('browser.download.dir', download)
                    profile.set_preference('browser.download.folderList', 2)
                else:
                    profile.set_preference('browser.download.folderList', 1)
                profile.set_preference('browser.download.manager.showWhenStarting', False)
                if saveAsFlag == 0:
                    profile.set_preference('browser.helperApps.neverAsk.saveToDisk', 'application/zip')
                self.driver = webdriver.Firefox(firefox_profile=profile, executable_path=webDriverPath)
            elif browserType == r'ie':
                self.driver = webdriver.Ie(webDriverPath)
            elif browserType == r'chrome':
                # options = Options()
                options = webdriver.ChromeOptions()
                options.add_experimental_option('w3c', False)
                options.add_argument('disable-infobars')                 # 禁用浏览器正在被自动化程序控制的提示
                # options.add_argument('--incognito')                    # 隐身模式（无痕模式）
                if isCloseBrowser:
                    options.add_argument('--headless')                     # 开启无界面模式
                # options.add_argument("--disable-gpu")                  # 禁用gpu
                options.add_argument('--user-agent=Mozilla/5.0 HAHA')  # 配置对象添加替换User-Agent的命令
                # options.add_argument('--window-size=1366,768')         # 设置浏览器分辨率（窗口大小）
                options.add_argument('--start-maximized')              # 最大化运行（全屏窗口）,不设置，取元素会报错
                options.add_argument('--disable-javascript')           # 禁用javascript
                # 去掉不受支持的命令行标记
                # options.add_experimental_option("excludeSwitches", ["ignore-certificate-errors"])
                # chrome下载设置
                if saveAsFlag == 0:
                    if download:
                        prefs = {'profile.default_content_settings.popups': 0, 'download.default_directory': download}
                    else:
                        prefs = {'profile.default_content_settings.popups': 0}
                else:
                    prefs = {'profile.default_content_settings.popups': 1}
                options.add_experimental_option('prefs', prefs)
                logger.info('webDriverPath:' + webDriverPath)
                self.driver = webdriver.Chrome(webDriverPath, chrome_options=options)
            # 加入隐式等待，在查找元素时触发轮询  20210519
            self.driver.implicitly_wait(6)
            self.driver.maximize_window()
        except Exception as msg:
            logger.error(msg)
            # setFail("打开浏览器出错!")

    def open_url(self, webURL):
        # 打开网址
        logger.info('打开网页： ' + webURL)
        self.driver.get(webURL)
        return self.driver

    def action_js(self, js_script):
        # 点击
        # document.querySelector("#frame_navigation_athena_dijit_TemplatePanel_indexDetailPanel_nc-all_checkbox").click()
        result = self.driver.execute_script(js_script)
        return result

    def display_wait(self, exceptElement=None, flag=1, timeout=30):
        '''
        显示等待，等待元素加载或判断其他条件成立
        :param exceptElement: 期望出现的元素
        :param flag:
            0：判断指定元素是否加载出来
            1: 判断某个元素是否可见. 可见代表元素非隐藏，并且元素的宽和高都不等于0，传入参数是元组类型的locator
            2：判断元素是否被选中
            3：判断frame是否可切入，可传入locator元组或者直接传入定位方式：id、name、index或WebElement
            4: 判断元素的 text 是否包含预期字符串
            5: 与0相反，判断某个元素消失继续
            6：判断弹框是否出现
            other：判断一个元素是否仍在DOM中，传入WebElement对象，可以判断页面是否刷新了
        :param timeout: 超时时间，默认30s
        :return: 得到期望值返回True，如果超时都未找到则返回False
        '''
        try:
            if exceptElement:
                ex_type, ex_str = exceptElement.split(":")
            wait = WebDriverWait(driver=self.driver, timeout=timeout, poll_frequency=1)
            if flag == 0:
                logger.info(f'等待指定元素加载完成:{ex_str}')
                res = wait.until(EC.presence_of_element_located((ex_type, ex_str)))
                return True if res else False
            elif flag == 1:
                logger.info(f'等待元素加载可见：{ex_str}')
                res = wait.until(EC.visibility_of_all_elements_located((ex_type, ex_str)))
                return True if res else False
            elif flag == 2:
                logger.info(f'判断元素是否选中:{ex_str}')
                wait.until(EC.element_located_to_be_selected((ex_type, ex_str)))
            elif flag == 3:
                logger.info(f'等待切换Frame完成:{ex_str}')
                wait.until(EC.frame_to_be_available_and_switch_to_it((ex_type, ex_str)))
            elif flag == 4:
                logger.info(f'判断元素是否存在期望的文本:{ex_str}')
                wait.until(EC.text_to_be_present_in_element((ex_type, ex_str)))
            elif flag == 5:
                logger.info(f'等待元素消失:{ex_str}')
                res = wait.until_not(EC.visibility_of_element_located((ex_type, ex_str)))
                return res
            elif flag == 6:
                logger.info(f'等待弹框出现!')
                res = wait.until(EC.alert_is_present())
                if res:
                    res_text = res.text
                    logger.info(f'弹框的文本是： {res_text}')
                return True if res else False
            else:
                wait.until(EC.staleness_of((ex_type, ex_str)))
            logger.info("查询操作完成！")
            return True
        except TimeoutException as e:
            logger.error(f"等待元素{ex_str}加载超时！")
            return None
        
    def browerRefresh(self):
        self.driver.refresh()
        return True
    
    # 添加cookies
    def add_cookies(self, cookies):
        for i in cookies:
            self.driver.add_cookie(i)
        self.driver.refresh()
        return self.driver

    def delete_cookies(self):
        self.driver.delete_all_cookies()

    def get_cookies(self):
        cookies = self.driver.get_cookies()
        logger.info(f'cookies:{cookies}')
        return cookies

    def classType(self):
        return r'UI'

    def switchToFrame(self, frameName=None, isParent=False):
        '''切换Frame，默认切换到主页'''
        if isParent:
            self.driver.switch_to.parent_frame()
            logger.info("切换到上一层frame")
        else:
            if isinstance(frameName, str) or isinstance(frameName, int):
                self.driver.switch_to.frame(frameName)
                logger.info("切换frame到" + str(frameName))
            elif isinstance(frameName, ElementObject):
                self.driver.switch_to.frame(frameName)
                logger.info("切换frame到" + str(frameName))
            else:
                self.driver.switch_to.default_content()
                logger.info("切换frame到主页")

    def getAllFrame(self,elementObj):
        # 获取当前元素下所有的frame、iframe
        frameList=elementObj.find_elements("tag name", "frame")
        iframeList=elementObj.find_elements("tag name", "iframe")
        frameList.extend(iframeList)
        tempList=[ElementObject(self,x) for x in frameList]
        return tempList

    def getElementByAttribute(self, attribute, getAll=False, TIMEOUT=6):
        '''
        根据属性查找目标元素；已增强函数的健壮性，会自动过滤非当前页面的元素；增加异常情况判断并返回。
        :param attribute: 属性类型和表达式；支持 xpath|name|class_name|tag_name|link_text|partial_link_text|css_selector 类型
        :param getAll: 是否获取所有值，默认只获取第1个匹配值
        :param TIMEOUT: 查找的超时时间
        :return: 
            情况1：getAll=False，返回单个元素，是 ElementObject 对象，可调用 ElementObject 类的方法
            情况2：getAll=True，返回一个列表，每个元素都是 ElementObject 对象，可调用 ElementObject 类的方法
        '''
        timeout = 0
        elements = None
        tempList = []
        if not attribute:
            logger.error(f'定位表达式为空：{attribute}')
            raise SeleniumError(f'定位表达式"{attribute}"为空')
        # 分离属性和表达式  2022-1-18 更新。替换split()方法，解决xpath表达式内有：时导致分割错误的问题。便于使用xpath的高级用法
        pattern_str = re.compile(r'(xpath|id|name|class_name|tag_name|link_text|partial_link_text|css_selector):(.*)', re.I)
        res_express = pattern_str.match(attribute)
        if res_express:
            primaryKey, primaryValue = res_express[1], res_express[2]
            logger.debug(f'查找类型：{primaryKey}，表达式：{primaryValue}')
        else:
            logger.error(f'定位表达式为空：{attribute}')
            raise SeleniumError(f'定位表达式正则匹配结果为空：{attribute}')

        # 已经加了隐式等待，设置时间为6s，找不到就返回None  2021-5-28
        elements = self.driver.find_elements(primaryKey, primaryValue)
        if not elements:
            logger.error(attribute + "属性对象没有找到!")
            raise SeleniumError(f"'{attribute}' 属性对象没有找到!")
        if getAll:
            for x in elements:
                if x.is_displayed():   # 筛选掉不在当前页面显示/能操作的元素 2022-1-18
                    tempList.append(ElementObject(self, x))
            return tempList
        else:
            lenNumber = len(elements)
            if lenNumber < 1:
                logger.error(f'{attribute} 未找到目标元素，请确认定位表达式正确性!')
                return None
            elif lenNumber == 1:
                # return ElementObject(self, elements[0])
                timeout = 0
                if not elements[0].is_displayed():
                    try:
                        elements[0].location_once_scrolled_into_view()
                        logger.info(f'{attribute} 元素不可见，第1次滚动页面')
                    except:
                        pass
                while (not elements[0].is_displayed()) and timeout < TIMEOUT:
                    time.sleep(0.5)
                    try:   # 滚动页面，让元素可见
                        elements[0].location_once_scrolled_into_view()
                        logger.info(f'{attribute} 元素不可见，第{timeout*2+1}次滚动页面')
                    except:
                        pass
                    timeout += 0.5
                if elements[0].is_displayed():
                    return ElementObject(self, elements[0])
                else:
                    logger.warning(attribute + "属性对象不可以操作，请确认!")
                    raise SeleniumError(f'{attribute} 属性对象不可以操作，请确认!')
            else:
                for x in elements:
                    if x.is_displayed():     # 筛选掉不在当前页面显示/能操作的元素 2022-1-18
                        tempList.append(ElementObject(self, x))
                if len(tempList) > 1:
                    logger.warning(f'getAll=False，{attribute} 表达式仍就找到多个元素，请确认定位表达式正确性!')
                    raise SeleniumError(f'getAll=False，{attribute} 表达式仍就找到多个元素，请确认定位表达式正确性!')
                else:
                    return tempList[0]


    def findElement(self, element, flag=True, timeout=10, fre_time=0.5):
        if flag == True:
            elementObj = self.driver.find_element_by_xpath(element)
        else:
            try:
                wait = WebDriverWait(self.driver, timeout, fre_time)
                elementObj = wait.until(EC.presence_of_element_located((By.XPATH, element)))
            except TimeoutException as e:
                raise e
        return elementObj


    def getScreen(self):
        # 截图函数
        try:
            cur_time = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
            png_name = cur_time + '.png'
            pngFile = os.path.join(logFilePath, png_name)
            self.driver.get_screenshot_as_file(pngFile)
            logger.info("Web自动化测试断言失败，截图路径：" + pngFile)
        except BaseException as e:
            logger.error("Failed to take Screenshots! %s" % e)

    def getAlert(self, alertFlag='accept', TIMEOUT=10):
        # alertOpen：对弹出框的操作，accept为确定，dismiss为取消
        timeout = 0
        alert = None
        while timeout <= TIMEOUT:
            try:
                alert = self.driver.switch_to.alert
                break
            except SeleniumExceptions.NoAlertPresentException as e:
                timeout += 1
                time.sleep(1)
        if alert:
            alerText = alert.text
            logger.info("弹出框显示：" + alerText)
            if alertFlag == 'dismiss':
                alert.dismiss()
                logger.info("弹出框点击“取消”！")
            else:
                alert.accept()
                logger.info("弹出框点击“确认”！")
        else:
            alerText = '无弹框'
            logger.warning("此处没有弹出框！！!")
        return alerText

    def act_script(self, element1):
        self.driver.execute_script("arguments[0].click();", element1)

    def getAttriMethod(self, elementobj, arribiteName):
        js = f'arguments[0].getAttribute("{arribiteName}");'
        logger.info(f'Act js: {js}')
        res = self.driver.execute_script(js, elementobj)
        return res

    def removeAttriMethod(self, elementobj, arribiteName):
        js = f'arguments[0].removeAttribute("{arribiteName}")'
        logger.info(f'Act js: {js}')
        res = self.driver.execute_script(js, elementobj)
        return res
    
    def setAttriMethod(self, elementobj, arribiteName, value):
        js = f'arguments[0].setAttribute("{arribiteName}", "{value}");'
        logger.info(f'Act js: {js}')
        res = self.driver.execute_script(js, elementobj)
        return res

    def modifyAttriMethod(self, elementobj, attributeName, value):
        '''
        功能：修改标签的属性
        :param elementobj: find方法找到返回的html对应的element
        :param attributeName: attributeName为innerHTML时，可以修改标签的text值
        :param value: 属性值
        :return:
        '''
        js = f'arguments[0].{attributeName}="{value}";'
        logger.info(f'Act js: {js}')
        res = self.driver.execute_script(js, elementobj)
        return res

    def _focusElementObject(self, ElementObject):
        # 页面发生滚动，使element的顶部与视图顶部对齐
        self.driver.execute_script("arguments[0].scrollIntoView();", ElementObject.changetoWebElement())

    def _scrollElementObject(self, ElementObject):
        self.driver.execute_script("arguments[0].scrollByLines(20);", ElementObject.changetoWebElement())

    def getScrollHeightOfElementObject(self, ElementObject):
        # ie\chrome获取元素内容实际高度
        return self.driver.execute_script("return arguments[0].scrollHeight;", ElementObject.changetoWebElement())

    def getScrollWidthOfElementObject(self,ElementObject):
        # ie/chrome获取元素内容实际宽度
        return self.driver.execute_script("return arguments[0].scrollWidth;", ElementObject.changetoWebElement())

    def scrollTopOfElementobject(self, ElementObject, height=100):
        # ie/chrome通过scrollTop属性给值来实现滚动条上下滚动
        self.driver.execute_script("return arguments[0].scrollTop=arguments[1];", ElementObject.changetoWebElement(), height)

    def scrollLeftOfElementobject(self, ElementObject, width=200):
        # ie/chrome通过scrollLeft属性给值来实现滚动条左右滚动
        self.driver.execute_script("return arguments[0].scrollLeft=arguments[1];", ElementObject.changetoWebElement(), width)

    def actJS(self, js_function, elementobj):
        js = f'arguments[0].{js_function};'
        logger.info(f'Act js: {js}')
        res = self.driver.execute_script(js, elementobj)
        return res

    def writeTableInfo(self, targetElement, value):
        # 双击/写值/提交执行，应用场景表格添加值
        tep = ActionChains(self.driver)
        tep.double_click(targetElement)
        for i in range(100):
            tep.send_keys(Keys.BACK_SPACE)
        tep.send_keys(value)
        tep.perform()

    def doubleClick(self, targetElement):
        # 双击
        ActionChains(self.driver).double_click(targetElement).perform()

    def rightClick(self, targetElement):
        # 右键单击
        ActionChains(self.driver).context_click(targetElement).perform()

    def leftClick(self, targetElement):
        # 左键单击
        ActionChains(self.driver).click(targetElement).perform()

    def moveToElement(self, targetElement):
        # 移动元素
        ActionChains(self.driver).move_to_element(targetElement).perform()

    def close(self):
        self.driver.quit()

    def fingerTap(self, ElementObject):
        TouchActions(self.driver).tap(ElementObject.changetoWebElement()).perform()

    def fingerDoubleTap(self, ElementObject):
        TouchActions(self.driver).double_tap(ElementObject.changetoWebElement()).perform()

    def fingerTapAndHold(self, X_position=0, Y_position=0):
        TouchActions(self.driver).tap_and_hold(X_position, Y_position).perform()

    def fingerMove(self, X_position=0, Y_position=0):
        TouchActions(self.driver).move(X_position, Y_position).perform()

    def fingerRelease(self, X_position=0, Y_position=0):
        TouchActions(self.driver).release(X_position, Y_position).perform()

    def fingerLongPress(self, ElementObject):
        TouchActions(self.driver).long_press(ElementObject.changetoWebElement()).perform()

    def fingerScroll(self, X_offset=0, Y_offset=0):
        TouchActions(self.driver).scroll(X_offset, Y_offset).perform()

    def fingerScrollFromElement(self, ElementObject, X_offset=0, Y_offset=0):
        TouchActions(self.driver).scroll_from_element(ElementObject.changetoWebElement(), X_offset, Y_offset).perform()

    def fingerFlick(self, X_speed=0, Y_speed=0):
        TouchActions(self.driver).flick(X_speed, Y_speed).perform()

    def fingerFlickElement(self, ElementObject, X_position=0, Y_position=0, speed=0):
        TouchActions(self.driver).flick_element(ElementObject.changetoWebElement(), X_position, Y_position, speed).perform()

    def getAllFrame(self, element):
        # 获取所有的frame
        frameList = element.find_elements("tag name", "frame")
        iframeList = element.find_elements("tag name", "iframe")
        frameList.extend(iframeList)
        tempList = [ElementObject(self, x) for x in frameList]
        return tempList

    def exist(self, attribute, timeOut=None):
        try:
            if timeOut:
                findResult = self.getElementByAttribute(attribute, timeout=timeOut)
            else:
                findResult = self.getElementByAttribute(attribute)
        except SeleniumError:
            findResult = None
        return findResult

    def isDisplayed(self,attribute):
        try:
            findResult=self.getElementByAttribute(attribute)
        except NoisePlayError:
            return False
        return findResult

    def closeBrowser(self):
        self.driver.quit()

class ElementObject(ClassSelenium):
    def __init__(self, driver, elementObj):
        self.elementObj = elementObj
        self.id = elementObj.id
        self.parent = elementObj._parent
        self.driver = driver
        self.w3c = elementObj._w3c

    def send_keys(self,inputStr):
        self.elementObj.send_keys(inputStr)

    def keyboard(self, inputStr):
        self.elementObj.send_keys(eval('Keys.' + inputStr))

    def getAttribute(self, inputStr):
        return self.elementObj.get_attribute(inputStr)


    def isReadOnly(self):
        findResult = self.getAttribute('readonly')
        if findResult == None:
            return False
        else:
            return True

    def _focusElement(self):
        ClassSelenium._focusElementObject(self.driver, self.elementObj)

    def findElements(self, tagname):
        lst = self.elementObj.find_elements_by_xpath(tagname)
        num = len(lst)
        return num

    def click(self):
        while True:
            try:
                self.elementObj.click()
                break
            except Exception as msg:
                logger.error(msg)
                # 处理可能出现的元素不在界面显示，无法点击的问题，将使用滚动条切换到可显示指定元素的位置，然后再做一次点击操作
                ExceptionStr = '{0}'.format(msg)
                if 'Element is not clickable at point' in ExceptionStr:
                    self._focusElement()
                else:
                    logger.error(msg)
                    raise msg

    def getTableTitle(self):
        if self.getTagName() == 'table':
            titleList = list()
            thread = self.elementObj.getElementByAttribute(r'tag name:thead')
            trList = thread.getElementByAttribute("tag name:tr", getAll=True)
            for tr in trList:
                try:
                    tList = tr.getElementByAttribute("tag name:td", getAll=True)
                except:
                    tList = tr.getElementByAttribute("tag name:th", getAll=True)
                for t in tList:
                    text = t.getText()
                    titleList.append(text)
            return titleList
        else:
            logger.error('元素对象不为table对象，对象类型为：'+self.getTagName())
            raise SeleniumError('元素对象不为table对象，对象类型为：' + self.getTagName())

    def getTableText(self):
        if self.getTagName()=='table':
            bodyList = list()
            tBody=self.elementObj.getElementByAttribute(r'tag name:tbody')
            trList=tBody.getElementByAttribute("tag name:tr",getAll=True)
            for tr in trList:
                try:
                    tList = tr.getElementByAttribute("tag name:td",getAll=True)
                except:
                    tList = tr.getElementByAttribute("tag name:th", getAll=True)
                for t in tList:
                    text = t.gettext()
                    bodyList.append(text)
            return bodyList
        else:
            logger.error('元素对象不为table对象，对象类型为：'+self.getTagName())
            raise SeleniumError('元素对象不为table对象，对象类型为：'+self.getTagName())

    def getTableCellByTitleAndRow(self,titleName,rowNumber):
        """
        getTableCellByTitleAndRow:根据列名和行数获取单元格元素对象
        titleName:标题名字
        rowNumber:行数
        """
        if self.getTagName() == 'table':
            titleNames = []
            #需要判断第一个是否为无标题全选框
            titleElements = self.elementObj.getElementByAttribute(r'tag name:thead').getElementByAttribute('tag name:tr').getElementByAttribute(r'tag name:th', True)
            for each in titleElements:
                if each.getText():
                    titleNames.append(each.getText())
                else:
                    #如果不存在text属性，则以name属性代替
                    titleNames.append(each.getElementByAttribute('tag name:input').getAttribute('name'))
            #找出当前title在titles中的列数
            titleIndex = titleNames.index(titleName)
            tableTextElements = self.elementObj.getElementByAttribute(r'tag name:tbody').getElementByAttribute('tag name:tr', True)
            tableRowElement = tableTextElements[rowNumber - 1]
            tableCellElements = tableRowElement.getElementByAttribute(r'tag name:td', True)
            tableCellElement = tableCellElements[titleIndex]
            return tableCellElement
        else:
            logger.error('元素对象不为table对象，对象类型为：'+self.getTagName())
            raise SeleniumError('元素对象不为table对象，对象类型为：'+self.getTagName())

    def getRowByTitleAndText(self, titleName, text):
        """
        getRowByTitleAndText:获取指定文本在表格中第一次出现的行数
        titleName:标题名字
        text:需要查找的文本
        """
        if self.getTagName() == 'table':
            titleNames = []
            row = 1
            #需要判断第一个是否为无标题全选框
            titleElements = self.elementObj.getElementByAttribute(r'tag name:thead').getElementByAttribute('tag name:tr').getElementByAttribute(r'tag name:th', True)
            for each in titleElements:
                if each.getText():
                    titleNames.append(each.getText())
                else:
                    #如果不存在text属性，则以name属性代替
                    titleNames.append(each.getElementByAttribute('tag name:input').getAttribute('name'))
            #找出当前title在titles中的列数
            titleIndex = titleNames.index(titleName)
            tableTextElements = self.elementObj.getElementByAttribute(r'tag name:tbody').getElementByAttribute('tag name:tr', True)
            #逐条寻找指定文本
            for each in tableTextElements:
                tableCellElements = each.getElementByAttribute(r'tag name:td', True)
                tableCellElement = tableCellElements[titleIndex]
                if tableCellElement.getText() == text:
                    return row
                else:
                    row += 1
                    logger.error('在table中的' + titleName + '列下没有找到' + text + '内容单元格')
            raise SeleniumError('在table中的' + titleName + '列下没有找到' + text + '内容单元格')
        else:
            logger.error('元素对象不为table对象，对象类型为：'+ self.getTagName())
            raise SeleniumError('元素对象不为table对象，对象类型为：'+ self.getTagName())

    def getText(self):
        return self.elementObj.text

    def getAttributeText(self):
        return self.elementObj.get_attribute("value")

    def isEnabled(self):
        return self.elementObj.is_enabled()

    def getsize(self):
        return self.elementObj.size

    def getLocation(self):
        return self.elementObj.location

    def getTagName(self):
        return self.elementObj.tag_name

    def isenabled(self):
        return self.elementObj.is_enabled()

    def changeToWebElement(self):
        return self.elementObj.WebEleget_attributement(self.parent, self.id, self.w3c)

    def clear(self):
        self.elementObj.clear()

    def select(self, value):
        """
        select:对下拉框对象进行选取操作
        value:下拉框的值
        """
        if self.getTagName() == 'select':
            #需要判断第一个是否为无标题全选框
            titleElements = self.elementObj.getElementByAttribute(r'tag name:option', True)
            for each in titleElements:
                if each.getText() == value:
                    each.click()
                    return 'pass'
                logger.error('在下拉框中下没有找到' + value + '选项')
            raise SeleniumError('在下拉框中下没有找到' + value + '选项')
        else:
            logger.error('元素对象不为下拉框对象，对象类型为：'+ self.getTagName())
            raise SeleniumError('元素对象不为下拉框对象，对象类型为：'+ self.getTagName())

class SeleniumError(Exception):
    def __init__(self, value):
        self.value = value

    def __str__(self):
        return repr(self.value)


class NoisePlayError(Exception):
    def __init__(self, value):
        self.value = value

    def __str__(self):
        return repr(self.value)


class WebElementEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, WebElement):
            return obj._id
        return json.JSONEncoder.default(self, obj)


if __name__ == '__main__':
    pass
